#include <string.h> // memcpy
#include <stdint.h>

#include <vector>


#define KEYSIZE 32

typedef unsigned __int128 uint128_t;

typedef uint64_t fe25519[5];

typedef struct {
	fe25519 X;
	fe25519 Y;
	fe25519 Z;
	fe25519 T;
} ge25519;

typedef struct {
	fe25519 X;
	fe25519 Y;
	fe25519 Z;
} ge25519_p2;

typedef struct {
	fe25519 X;
	fe25519 Y;
	fe25519 Z;
	fe25519 T;
} ge25519_p3;

typedef struct {
	fe25519 X;
	fe25519 Y;
	fe25519 Z;
	fe25519 T;
} ge25519_p1p1;

typedef struct {
	fe25519 yplusx;
	fe25519 yminusx;
	fe25519 xy2d;
} ge25519_precomp;

class x25519
{
public:
	x25519();
	void init_private_key(const uint8_t privateKey[KEYSIZE]);
	void mutate_private_key();
	void get_public_key(uint8_t publicKey[KEYSIZE]);
	void get_private_key(uint8_t privateKey[KEYSIZE]);

private:
	void ge25519_scalarmult_base(ge25519_p3 *h);

private:
	ge25519 basePowers[255];

	int keyBits[256];
	std::vector<ge25519> state;
};